//SPDX-FileCopyrightText: Copyright 2022-2024 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package user_mail_api_serv

import (
	"context"

	"atomgit.com/openlinksaas-org/api-server/dao"
	"atomgit.com/openlinksaas-org/api-server/dao/mail_dao"
	"atomgit.com/openlinksaas-org/proto-gen-go.git/user_mail_api"
	"go.mongodb.org/mongo-driver/mongo"
)

func (apiImpl *UserMailApiImpl) GetMailStatus(ctx context.Context, req *user_mail_api.GetMailStatusRequest) (*user_mail_api.GetMailStatusResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &user_mail_api.GetMailStatusResponse{
			Code:   user_mail_api.GetMailStatusResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	allCount, err := mail_dao.MailInfoDao.Count(ctx, sessionItem.UserId, false, false)
	if err != nil {
		return nil, err
	}
	hasReadCount, err := mail_dao.MailInfoDao.Count(ctx, sessionItem.UserId, true, true)
	if err != nil {
		return nil, err
	}
	return &user_mail_api.GetMailStatusResponse{
		Code:         user_mail_api.GetMailStatusResponse_CODE_OK,
		AllCount:     allCount,
		HasReadCount: hasReadCount,
	}, nil
}

func (apiImpl *UserMailApiImpl) ListMail(ctx context.Context, req *user_mail_api.ListMailRequest) (*user_mail_api.ListMailResponse, error) {
	emptyList := []*user_mail_api.MailInfo{}

	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &user_mail_api.ListMailResponse{
			Code:     user_mail_api.ListMailResponse_CODE_WRONG_SESSION,
			ErrMsg:   "会话不存在",
			InfoList: emptyList,
		}, nil
	}

	count, err := mail_dao.MailInfoDao.Count(ctx, sessionItem.UserId, req.FilterByHasRead, req.HasRead)
	if err != nil {
		return nil, err
	}
	infoItemList, err := mail_dao.MailInfoDao.List(ctx, sessionItem.UserId, req.FilterByHasRead, req.HasRead, int64(req.Offset), int64(req.Limit))
	if err != nil {
		return nil, err
	}
	infoList := []*user_mail_api.MailInfo{}
	for _, infoItem := range infoItemList {
		infoList = append(infoList, infoItem.ToMailInfo())
	}

	return &user_mail_api.ListMailResponse{
		Code:       user_mail_api.ListMailResponse_CODE_OK,
		TotalCount: count,
		InfoList:   infoList,
	}, nil
}

func (apiImpl *UserMailApiImpl) GetMailDetail(ctx context.Context, req *user_mail_api.GetMailDetailRequest) (*user_mail_api.GetMailDetailResponse, error) {
	emptyInfo := &user_mail_api.MailInfo{}

	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &user_mail_api.GetMailDetailResponse{
			Code:   user_mail_api.GetMailDetailResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
			Info:   emptyInfo,
		}, nil
	}
	infoItem, err := mail_dao.MailInfoDao.Get(ctx, sessionItem.UserId, req.MailId)
	if err != nil {
		return &user_mail_api.GetMailDetailResponse{
			Code:   user_mail_api.GetMailDetailResponse_CODE_NO_MAIL,
			ErrMsg: "邮件不存在",
			Info:   emptyInfo,
		}, nil
	}
	bodyItem, err := mail_dao.MailBodyDao.Get(ctx, req.MailId)
	if err != nil {
		return &user_mail_api.GetMailDetailResponse{
			Code:   user_mail_api.GetMailDetailResponse_CODE_NO_MAIL,
			ErrMsg: "邮件不存在",
			Info:   emptyInfo,
		}, nil
	}

	return &user_mail_api.GetMailDetailResponse{
		Code:     user_mail_api.GetMailDetailResponse_CODE_OK,
		Info:     infoItem.ToMailInfo(),
		TextBody: bodyItem.Text,
		HtmlBody: bodyItem.Html,
	}, nil
}

func (apiImpl *UserMailApiImpl) RemoveMail(ctx context.Context, req *user_mail_api.RemoveMailRequest) (*user_mail_api.RemoveMailResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &user_mail_api.RemoveMailResponse{
			Code:   user_mail_api.RemoveMailResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	exist, err := mail_dao.MailInfoDao.Exist(ctx, sessionItem.UserId, req.MailId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &user_mail_api.RemoveMailResponse{
			Code: user_mail_api.RemoveMailResponse_CODE_OK,
		}, nil
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = mail_dao.MailInfoDao.Remove(sessCtx, sessionItem.UserId, req.MailId)
		if err != nil {
			return nil, err
		}
		err = mail_dao.MailBodyDao.Remove(sessCtx, req.MailId)
		if err != nil {
			return nil, err
		}
		return &user_mail_api.RemoveMailResponse{
			Code: user_mail_api.RemoveMailResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	return ret.(*user_mail_api.RemoveMailResponse), nil
}

func (apiImpl *UserMailApiImpl) SetMailState(ctx context.Context, req *user_mail_api.SetMailStateRequest) (*user_mail_api.SetMailStateResponse, error) {
	sessionItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &user_mail_api.SetMailStateResponse{
			Code:   user_mail_api.SetMailStateResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	exist, err := mail_dao.MailInfoDao.Exist(ctx, sessionItem.UserId, req.MailId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &user_mail_api.SetMailStateResponse{
			Code:   user_mail_api.SetMailStateResponse_CODE_NO_MAIL,
			ErrMsg: "邮件不存在",
		}, nil
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = mail_dao.MailInfoDao.UpdateHasRead(sessCtx, sessionItem.UserId, req.MailId, req.HasRead)
		if err != nil {
			return nil, err
		}
		return &user_mail_api.SetMailStateResponse{
			Code: user_mail_api.SetMailStateResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	return ret.(*user_mail_api.SetMailStateResponse), nil
}
